package com.mybatisflex.admin.controller;

import com.mybatisflex.admin.entity.Account;
import com.mybatisflex.admin.interceptor.LoginInterceptor;
import com.mybatisflex.admin.service.AccountService;
import com.mybatisflex.admin.spring.jsonbody.JsonBody;
import com.mybatisflex.admin.util.HashUtil;
import com.mybatisflex.admin.util.ImageUtil;
import com.mybatisflex.admin.util.JwtUtil;
import com.mybatisflex.admin.util.Result;
import com.mybatisflex.core.mask.MaskManager;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import static com.mybatisflex.admin.entity.table.AccountTableDef.ACCOUNT;

/**
 * 控制层。
 *
 * @author michael
 * @since 2023-07-01
 */
@RestController
@RequestMapping("/api/account")
public class AccountController {

    @Autowired
    private AccountService accountService;

    /**
     * 登录
     *
     * @param username 账号
     * @param password 密码
     */
    @PostMapping("/login")
    public Result login(@JsonBody("username") String username, @JsonBody("password") String password) {
        Result result = accountService.login(username, password);
        if (result.isSuccess()) {
            Map<String, Object> map = new HashMap<>();
            map.put(LoginInterceptor.loginSessionId, result.get(LoginInterceptor.loginSessionId));
            String token = JwtUtil.createToken(map);
            result.set("jwt", token);
        }
        return result;
    }


    /**
     * 个人资料详情
     */
    @GetMapping("/detail")
    public Result detail() {
        Account account = accountService.getById(LoginInterceptor.getLoginAccountId());
        account.setPassword(null);
        account.setSalt(null);
        return Result.success("account", account);
    }


    /**
     * 分页查询。
     *
     * @param page 分页对象
     * @return 分页对象
     */
    @PostMapping("page")
    public Page<Account> page(@JsonBody Page<Account> page
            , @JsonBody("userName") String userName
            , @JsonBody("email") String email
            , @JsonBody("mobile") String mobile
    ) {
        QueryWrapper qw = QueryWrapper.create()
                .where(ACCOUNT.USER_NAME.eq(userName))
                .and(ACCOUNT.EMAIL.eq(email))
                .and(ACCOUNT.MOBILE.eq(mobile))
                .orderBy(ACCOUNT.ID.desc());
        return accountService.page(page, qw);
    }


    /**
     * 添加。
     *
     * @param account
     * @return {@code true} 添加成功，{@code false} 添加失败
     */
    @PostMapping("save")
    public Result save(@RequestBody Account account) {
        Account existAccount = accountService.getOne(ACCOUNT.USER_NAME.eq(account.getUserName()));
        if (existAccount != null) {
            return Result.error(1, "该用户名已存在，无法添加。");
        }
        return Result.create(accountService.save(account));
    }

    /**
     * 根据主键删除。
     *
     * @param id 主键
     * @return {@code true} 删除成功，{@code false} 删除失败
     */
    @GetMapping("remove/{id}")
    public Result remove(@PathVariable Serializable id) {
        Account account = accountService.getById(id);
        if (account == null) {
            return Result.error(1, "当前账户不存在，或已被删除。");
        }

        if (account.getId().equals(LoginInterceptor.getLoginAccountId())) {
            return Result.error(2, "不能删除自己。");
        }
        return Result.create(accountService.removeById(id));
    }

    /**
     * 根据主键更新。
     *
     * @param account
     * @return {@code true} 更新成功，{@code false} 更新失败
     */
    @PostMapping("update")
    public Result update(@RequestBody Account account) {
        String mobile = account.getMobile();
        if (mobile != null && mobile.contains("**")) {
            //不修改 mobile 数据
            account.setMobile(null);
        }
        return Result.create(accountService.updateById(account));
    }

    /**
     * 修改密码
     *
     * @return {@code true} 更新成功，{@code false} 更新失败
     */
    @PostMapping("updatePwd")
    public Result updatePwd(@JsonBody(value = "oldPwd", required = true) String oldPwd
            , @JsonBody(value = "newPwd", required = true) String newPwd
            , @JsonBody(value = "confirmPwd", required = true) String confirmPwd) {

        Account account = accountService.getById(LoginInterceptor.getLoginAccountId());
        String hashPassword = HashUtil.sha256(account.getSalt() + oldPwd);

        //旧密码不正确
        if (!hashPassword.equals(account.getPassword())) {
            return Result.error(1, "旧密码不正确。");
        }

        if (!newPwd.equals(confirmPwd)) {
            return Result.error(2, "密码和确认密码不一致。");
        }

        //修改密码
        boolean success = UpdateChain.of(Account.class)
                .set(Account::getPassword, hashPassword)
                .where(Account::getId).eq(account.getId())
                .update();

        return Result.success(success);
    }


    /**
     * 更新头像。
     *
     * @param mf
     * @return {@code true} 更新成功，{@code false} 更新失败
     */
    @PostMapping("update/avatar")
    public Result uploadAvatar(@RequestParam(value = "file") MultipartFile mf) throws IOException {
        if (mf == null || ImageUtil.notImage(mf.getOriginalFilename())) {
            return Result.error();
        }
        String path = ImageUtil.saveImage(mf);
        Account account = accountService.getById(LoginInterceptor.getLoginAccountId());
        account.setAvatar(path);
        accountService.updateById(account);
        return Result.success("path", path);
    }


    /**
     * 查询所有。
     *
     * @return 所有数据
     */
    @GetMapping("list")
    public Result list() {
        return Result.success(accountService.list());
    }

    /**
     * 根据主键获取详细信息。
     *
     * @param id 主键
     * @return 详情
     */
    @GetMapping("info/{id}")
    public Result info(@PathVariable Serializable id) {
        return MaskManager.execWithoutMask(() -> Result.success(accountService.getById(id)));
    }

    /**
     * 分页查询。
     *
     * @param page 分页对象
     * @return 分页对象
     */
    @GetMapping("page")
    public Page<Account> page(Page<Account> page) {
        return accountService.page(page);
    }

}